_Pragma("once");
/*
 * Author: lizb
 */

#include <memory>

#include "BoundedBuffer.h"
#include "Workable.h"

using std::shared_ptr;

template <class WORKER, class ELEMENT_TYPE, class POINT_TYPE = shared_ptr<ELEMENT_TYPE>>
class WithPoolWorkable : public Workable<WORKER>
{
public:
    typedef ELEMENT_TYPE ElementType;
    typedef POINT_TYPE PointType;
    typedef BoundedBuffer<PointType> PoolType;

    WithPoolWorkable(clock_t timeout = 0);
    virtual ~WithPoolWorkable();

    PoolType* getWorkPool()
    {
        return mpPool;
    }

    void setWorkPool(PoolType* pWorkPool)
    {
        mpPool = pWorkPool;
    }

    bool doWork();

// do not forget imeplement this function and not let there is virtual.
//    bool doWork(PointType& element);

protected:

    PoolType* mpPool;

    ELEMENT_TYPE mTimeoutElement;
    clock_t mTimeout;
};


template <class WORKER, class ELEMENT_TYPE, class POINT_TYPE>
WithPoolWorkable<WORKER, ELEMENT_TYPE, POINT_TYPE>::WithPoolWorkable(clock_t timeout) : mpPool(NULL), mTimeout(timeout)
{
}


template <class WORKER, class ELEMENT_TYPE, class POINT_TYPE>
WithPoolWorkable<WORKER, ELEMENT_TYPE, POINT_TYPE>::~WithPoolWorkable()
{
}


template <class WORKER, class ELEMENT_TYPE, class POINT_TYPE>
bool WithPoolWorkable<WORKER, ELEMENT_TYPE, POINT_TYPE>::doWork()
{
    PointType element;
    assert(mpPool);
    bool result = mpPool->popPool(&element, mTimeout, 1);
    if (false == result)
    {
        element = static_cast<POINT_TYPE> (&mTimeoutElement);
    }
    ((WORKER*)this)->processPoolItem(element);

    return true;
}


